/* -*- C++  -*- */
/*===========================================================
 
 .---=||||[ B L O O D Y ]|||||=====================----------....
 |                                                              |
 |    THE  M O S T   B L O O D Y  GAME EVER!                    |
 |                                                              |
 |    bloody harvest is coming... soon,                         |
 |                                              heil Satan!     |
 !                                                              !
 .                                                              ,
  ~~~~-------------================================|||||||||==-~




 Name-Space: {core, logic, editor}
 Module: {draw, coll, scgr, ...}
 Class: <name of class>
 Last modification:  <author>, <time>

 TODO:
 <-------- todo #1 ---------->
 <-------- todo #2 ---------->
 <-------- todo #3 ---------->
        ............
 <-------- todo #n ---------->

 FIX:
 <-------- fix #1 ----------->
 <-------- fix #1 ----------->
         ..........
 <-------- fix #n ----------->




 
 
 ============================================================*/
#ifndef __draw_Camera_Header_File__
#define __draw_Camera_Header_File__

#include "common.h"
#include "core/vmath.h"
#include "core/draw/ICamera.h"

namespace core
{
	namespace draw
	{
	

	  /**
	   * Follow camera class.
	   */
	  class FollowCam : public ICamera
	  {
			public:

				/**
				 * Gets position of camer.
				 * 
				 * @return Vector of camera position.
				 */
				Vector3f getPosition(){ return position; }

				/**
				 * Gets look at point position.
				 * 
				 * @return Look at position vector.
				 */
				Vector3f getLookAt(){ return lookAt; }

				/**
				 * Gets approximal up vector.
				 * 
				 * @return Approximal up vector.
				 */
				Vector3f getUp(){ return up; }

				/**
				 * Sets position of camera.
				 * 
				 * @param New value of position.
				 */
				void setPosition(Vector3f value){ position = value; }

				/**
				 * Sets look at point of camera.
				 * 
				 * @param New value of look at vector.
				 */
				void setLookAt(Vector3f value){ lookAt = value; }

				/**
				 * Sets approximal up vector of camera.
				 * 
				 * @param New value of approximal up vector.
				 */
				void setUp(Vector3f value){ up = value; }

				/**
				 * Basic constructor
				 */
				FollowCam();

				/**
				 * Basic destructor.
				 */
				virtual ~FollowCam();

				/**
				 * Updates OpenGL matrices to reflect current
				 * setup of this camera. 
				 * 
				 * @note This method must be called just after
				 * begining of new drawing pass.
				 */
				virtual void place();

			protected:
				/**
				 * Desired Position of camera
				 */
				Vector3f position;

				/**
				 * Desired Vector of object this camera looks at.
				 */
				Vector3f lookAt;

				/**
				 * Approximal up vector.
				 */
				Vector3f up;

				/**
				 * Current position of camera
				 */
				Vector3f curPos;

				/** 
				 * Current Look At point
				 */
				Vector3f curLookAt;

				/**
				 * Time of last place method call
				 */
				double lastTime;
	  };


	  class FPCam : public ICamera
	  {
			public:
				Vector3f position;
				Quatf rotation;
			public:
				FPCam();
				virtual ~FPCam();

				virtual void place();
	  };

		/**
		 * First Person Camera class
		 */
	  class FPSCam : public ICamera
	  {
			public:
				/**
				 * Position of camera
				 */
				Vector3f position;

				/**
				 * Azimut of viewing
				 */
				float azimut;

				/**
				 * Zenit of viewing
				 */
				float zenit;
			public:

				/**
				 * Creates new first person camera object.
				 */
				FPSCam();

				/**
				 * Destroys instance
				 */
				virtual ~FPSCam();
	    
				/**
				 * Setup OpenGL matricis acording to camera 
				 * settings.
				 */
				virtual void place();

				/**
				 * Moves forward with camera forward 
				 * (respecting azimut and zenit).
				 *
				 * @param len The length of motion.
				 */
				void moveForward(float len);

				/**
				 * Steps left with camera forward 
				 * (respecting azimut and zenit).
				 *
				 * @param len The length of motion.
				 */
				void moveLeft(float len);

				/**
				 * Steps right with camera forward 
				 * (respecting azimut and zenit).
				 *
				 * @param len The length of motion.
				 */
				void moveRight(float len);

				/**
				 * Moves backward with camera forward 
				 * (respecting azimut and zenit).
				 *
				 * @param len The length of motion.
				 */
				void moveBackward(float len);

			private:

				/**
				 * Computes rotation matrix depending on 
				 * azimut and zeint).
				 * 
				 * @return rotation matrix expressing camera
				 * azimut and zenit.
				 */
				Matrix3f rotMat();
	  };

	}
}

#endif //__draw_Camera_Header_File__
